package com.ruoyi.business.service.impl.sms;

import cn.hutool.core.date.DateTime;
import cn.hutool.core.lang.Validator;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import com.ruoyi.business.domain.SmsPushRecordDetails;
import com.ruoyi.business.mapper.SmsPushRecordDetailsMapper;
import com.ruoyi.business.mapper.SmsSendRecordMapper;
import com.ruoyi.business.service.ISmsService;
import com.ruoyi.common.constant.CacheConstants;
import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.redis.RedisUtils;
import com.ruoyi.sms.domain.bo.DwSmsBO;
import com.ruoyi.sms.domain.dto.DewinSendSmsResponse;
import com.ruoyi.sms.service.Dh3tSendSmsServiceImpl;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import java.time.Duration;

/**
 * 登录短信服务层 服务层
 *
 * @author Fgxia LD 99
 */
@Slf4j
@Service("smsLoginService")
@RequiredArgsConstructor
public class SmsLoginServiceImpl implements ISmsService {

    private final Dh3tSendSmsServiceImpl dh3tSendSmsService;

    private final SmsSendRecordMapper smsSendRecordMapper;

    private final SmsPushRecordDetailsMapper smsPushRecordDetailsMapper;

    /**
     * 发送验证码短信
     *
     * @param phone 手机号
     * @param code  验证码，可不传。不传则自动生成
     */
    @Override
    public Boolean send(String phone, String code) {
        if (StrUtil.isEmpty(phone) && !Validator.isMobile(phone)) {
            throw new ServiceException("手机号不能为空且必须符合格式要求");
        }
        // 判断参数
        String verifyKey = CacheConstants.CAPTCHA_CODE_KEY + phone;
        long expire = RedisUtils.getTimeToLive(verifyKey)/1000;
        // 判断发送频繁 60秒
        if (expire >= Constants.CAPTCHA_EXPIRATION - Constants.CAPTCHA_SHORT_TIME) {
            throw new ServiceException("验证码发送频繁");
        }
        // 判断当天发送次数
        Integer dayCnt = RedisUtils.getCacheMapValue(CacheConstants.SMS_SEND_CNT_KEY, phone);
        if (dayCnt != null && dayCnt >= Constants.CAPTCHA_DAY_LIMIT) {
            throw new ServiceException("当天发送次数已达上限");
        }
        if (StrUtil.isEmpty(code)) {
            // 生成验证码
            code = RandomUtil.randomNumbers(6);
        }
        DwSmsBO dwSmsBO = new DwSmsBO();
        dwSmsBO.setPhones(phone);
        dwSmsBO.setSms(StrUtil.format("您的验证码是：{}，请在10分钟内输入。如非本人操作，请忽略本短信。", code));
        // dwSmsBO.setBatch(null);
        DewinSendSmsResponse sendSmsResponse = dh3tSendSmsService.sendSms(dwSmsBO);
        log.info("信息发送状态：{}", sendSmsResponse);
        // 发送记录
        smsPushRecordDetailsMapper.insertSmsSendRecord(dwSmsBO, sendSmsResponse);
        if (sendSmsResponse.getCode().equals(Constants.SUCCESS)) {
            // 缓存验证码
            RedisUtils.setCacheObject(verifyKey, code, Duration.ofSeconds(Constants.CAPTCHA_EXPIRATION));
            // 增加发送限制
            RedisUtils.setCacheMapIncrement(CacheConstants.SMS_SEND_CNT_KEY, phone, 1);
            return true;
        } else {
            return false;
        }
    }
}
